<?php

namespace App\Admin\Controllers;

use App\Admin\Metrics\Examples;
use App\Http\Controllers\Controller;
use Dcat\Admin\Http\Controllers\Dashboard;
use Dcat\Admin\Layout\Column;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Grid;
use App\Models\Project;
use Dcat\Admin\Widgets\Card;
use Dcat\Admin\Admin;
use App\Models\SwitchModel;
use App\Models\SwitchData;
use App\Models\SwitchPoint;
use App\Models\SwitchElectric;
use Illuminate\Http\Request;
use Dcat\Admin\Widgets\Dropdown;
use App\Handlers\WeconHandler;

class SwitchDataController extends Controller
{
    const SELF_AUTO_REFRESH = 60;

    public function realtime(Content $content, $projectId, $id = 0)
    {   
        if (empty($id)) {
            $gateways = SwitchModel::where('project_id', $projectId)->distinct()->pluck('pid')->toArray();
            foreach ($gateways as $v) {
                if (empty($v)) {
                    continue;
                } else {
                    $box = $v;
                    break;
                }
            }
        } else {
            $gateway = $id;
        }

        Admin::css('/layui/css/layui.css');
        Admin::css('/css/card-switch.css');
        Admin::js('/js/card-switch.js');
        $sessionKey = 'switch_realtime_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        return $content
            ->header('实时数据')
            ->description(view('admin.switch.autoRefresh',['autoRefresh' => $autoRefresh, 'key' => $sessionKey]))
            ->body(function (Row $row) use ($gateway, $projectId) {
                $row->column(2, $this->realtimeMenuTree($gateway, $projectId));
                $row->column(10, function (Column $column) use ($gateway, $projectId) {
                    $column->row(function(Row $row) use ($gateway, $projectId) {
                        $switches = SwitchModel::where('project_id', $projectId)->where('pid', $gateway)->orderBy('id', 'desc')->pluck('name','id')->toArray();
                        foreach ($switches as $id => $name) {
                            $row->column(4, $this->realtimeSingleCard($id, $name, $projectId));
                        }
                    });
                });
            });
    }

    protected function realtimeMenuTree($gateway, $projectId){
        $switches = SwitchModel::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        foreach ($switches as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $gateway) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/switch-realtime').'/'.$projectId."/".$v['id'];
                foreach ($switches as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        $children['spread'] = true;
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/switch-realtime-detail').'/'.$vv['id'];
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.switch.realtimeMenuTree', $data));
        return $card;
    }

    protected function realtimeSingleCard($id, $name, $projectId){
        $data['url'] = url('admin/switch-realtime-detail').'/'.$id;
        $data['name'] = $name;
        $data['id'] = $id;

        $data['points'] = [];
        $data['latestData'] = [];
        $sessionKey = 'switch_realtime_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;;
        $data['time'] = time();

        $points = SwitchPoint::where('switch_id', $id)->pluck('name','alias');
        if ($points->isNotEmpty()) {           
            $fields = array_keys($points->toArray());
            $data['latestData'] = SwitchData::getJsonDataOne($id, array_merge($fields,['created_time']));
            if ($data['latestData']) {
                $data['time'] = $data['latestData']['created_time'];
                unset($data['latestData']['created_time']);
            } else {
                foreach ($points as $pointAlias => $pointName) {
                    $data['latestData'][$pointAlias] = 0;
                }
            }
            $data['points'] = $points;
        }
        $card = Card::make(view('admin.switch.realtime', $data));
        return $card;
    }
    
    public function getSwitchRealtimeData(Request $request){
        $param = $request->all();
        $switch = SwitchModel::find($param['switchId']);
        $jsonData = SwitchData::getLatestRedisData($switch['machine_code']);
        $data['time'] = date("Y-m-d H:i:s");
        $data['switchId'] = $param['switchId'];
        $data['latestData'] = $jsonData;
        return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
    }

    //*************************************************************************************************
    //*************************************************************************************************

    public function realtimeDetail(Content $content, $id = 0)
    {   
        $switch = SwitchModel::find($id);
        $sessionKey = 'switch_realtime_detail_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        Admin::css('/layui/css/layui.css');

        $points = SwitchPoint::where('switch_id', $id)->pluck('name','alias');

        if ($points->isEmpty()) {
            return $this->noRealtimeDetail($content, $switch['name']);
        }
        $fields = array_keys($points->toArray());
        $fields[] = 'created_time';
        $latestData = SwitchData::getJsonDataOne($id, $fields);
        if (!$latestData) {
            return $this->noRealtimeDetail($content, $switch['name']);
        }

        $this->realtimeDetailPolling($id, $latestData['created_time'], $autoRefresh, $fields);   //轮询js

        return $content
            ->header($switch['name'])
            ->description(view('admin.switch.autoRefresh',['autoRefresh' => $autoRefresh, 'key' => $sessionKey]))
            ->body(function (Row $row) use ($id, $points, $latestData) {
                $row->column(2, $this->realtimeDetailMenuTree($id));
                $row->column(10, function (Column $column) use ($id, $points, $latestData) {
                    $column->row(function(Row $row) use ($id, $points, $latestData) {
                        foreach ($points as $k => $onePoint) {
                            if ($k == 'status') {
                                continue;
                            }
                            $row->column(4, $this->realtimeDetailSingleCard($id, $points, $k, $latestData));
                        }
                    });
                });
            });
    }

    protected function noRealtimeDetail($content, $name){
        return $content->header($name)
            ->description()
            ->body(function (Row $row) {
                $row->column(2, $this->realtimeDetailMenuTree());
                $row->column(10, Card::make('暂 无 数 据'));
            });
    }

    protected function realtimeDetailMenuTree($id){
        $switch = SwitchModel::find($id);
        $projectId = $switch['project_id'];
        $parentId = $switch['pid'];

        $switches = SwitchModel::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        foreach ($switches as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $parentId) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/switch-realtime').'/'.$projectId."/".$v['id'];
                foreach ($switches as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        $children['spread'] = true;
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/switch-realtime-detail').'/'.$vv['id'];
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.switch.realtimeDetailMenuTree', $data));
        return $card;
    }

    protected function realtimeDetailSingleCard($id, $points, $alias, $latestData){
        $data['url'] = url('admin/switch-monitor').'/'.$id.'-'.$alias;
        $data['name'] = $points[$alias];
        $data['value'] = $latestData[$alias];
        $data['deviceId'] = $id;
        $data['time'] = $latestData['created_time'];
        $data['alias'] = $alias;
        $sessionKey = 'switch_realtime_detail_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $card = Card::make(view('admin.switch.realtimeDetail', $data));
        return $card;
    }

    protected function realtimeDetailPolling($id, $latestTime, $autoRefresh, $fields){
        $url = url('admin/getSwitchRealtimeDetailData');
        $token = csrf_token();
        $fields = json_encode($fields);
        Admin::script(
<<<JS
    Dcat.ready(function () {
        console.log('start polling');
        getSwitchRealtimeDetailData()

        function getSwitchRealtimeDetailData() {
            setTimeout(getSwitchRealtimeDetailData, 1000*$autoRefresh);

            let url = "$url";
            let data = {
                _token: '$token',
                id: $id,
                time: $latestTime,
                fields: $fields
            }

            $.ajax({
                type : "POST",
                url : url,
                data : data,
                success : function(result) {
                    if (result.code == 1) {
                        $(".single-time").html(result.data.time)
                        const aliases = Object.keys(result.data.data)
                        console.log(aliases)
                        for(let i=0;i<aliases.length;i++){
                            let a = aliases[i];
                            if(a == 'status') {
                                continue;
                            }
                            eval( "option_" + a ).series[0].data[0].value = result.data.data[aliases[i]];
                            eval("myChart_" + a).setOption( eval( "option_" + a ) );    
                        }
                    } else {
                        console.log(result.msg)
                    }
                },
                //请求失败，包含具体的错误信息
                error : function(e){
                    layer.close(e);
                    console.log(e.status);
                    console.log(e.responseText);
                }
            });
        }
    });
JS
);
    }

    public function getSwitchRealtimeDetailData(Request $request){
        $param = $request->all();
        $switch = SwitchModel::find($param['id']);
        $jsonData = SwitchData::getLatestRedisData($switch['machine_code']);
        $data['time'] = date("Y-m-d H:i:s");
        $data['data'] = $jsonData;
        return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
    }

    //*************************************************************************************************
    //*************************************************************************************************
    
    public function monitor(Content $content, $id = 0)
    {   
        Admin::css('/layui/css/layui.css');
        $sessionKey = 'switch_monitor_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $info = explode('-', $id);
        $switchId = reset($info);
        $alias = end($info);
        $switch = SwitchModel::find($switchId);
        $point = SwitchPoint::where('switch_id', $switchId)->where('alias', $alias)->value('name');
        return $content
            ->header($switch['name'].'-'.$point)
            ->description(view('admin.switch.autoRefresh',['autoRefresh' => $autoRefresh, 'key' => $sessionKey]))
            ->body(function (Row $row) use ($switch, $alias, $point) {
                $row->column(2, $this->monitorMenuTree($switch));
                $row->column(10, function (Column $column) use ($switch, $alias, $point) {
                    $column->row(function(Row $row) use ($switch, $alias, $point) {
                        $row->column(12, '<div style="text-align: center; font-size: 22px;margin: 20px">'.$switch['name'].'-'.$point.'</div>');
                    });
                    $column->row($this->monitorData($switch, $alias));
                    $column->row($this->monitorChart($switch, $alias));
                });
            });
    }

    protected function monitorMenuTree($switch){
        $projectId = $switch['project_id'];

        $switches = SwitchModel::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        foreach ($switches as $k => $v) {
            if (!$v['pid']) {
                $one['spread'] = true;
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/switch-realtime').'/'.$projectId.'/'.$v['id'];
                //设备(电源柜)
                foreach ($switches as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        if ($vv['id'] == $switch['id']) {
                            $children['spread'] = true;
                        } else {
                            $children['spread'] = false;
                        }
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['isParent'] = true;
                        $children['url'] = url('admin/switch-realtime-detail').'/'.$vv['id'];
                        $children['children'] = [];
                        $points = SwitchPoint::where('switch_id', $vv['id'])->pluck('name', 'alias')->toArray();
                        //采集点
                        foreach ($points as $key => $value) {
                            $c['spread'] = true;
                            $c['title'] = $value;
                            $c['id'] = $vv['id'].'-'.$key;
                            $c['url'] = url('admin/switch-monitor').'/'.$c['id'];
                            array_push($children['children'], $c);
                        }
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.switch.monitorMenuTree', $data));
        return $card;
    }

    protected function monitorData($switch, $alias){
        $data = $this->getMonitorData($switch['id'], $alias);
        $sessionKey = 'switch_monitor_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $card = Card::make(view('admin.switch.monitorData', $data));
        return $card;
    }

    protected function getMonitorData($switchId, $alias, $latestTime = null){
        $latest = SwitchData::getJsonDataOne($switchId, [$alias, 'created_time'], $latestTime);
        if (!$latest) {
            return [];
        }

        $data['now'] = $latest[$alias];
        $data['time'] = date("Y-m-d H:i:s", $latest['created_time']);

        $start = strtotime(date("Y-m-d"));
        $end = time();

        $data['max'] = SwitchData::getMax($switchId, $alias, $start, $end);
        $data['min'] = SwitchData::getMin($switchId, $alias, $start, $end);
        $data['avg'] = SwitchData::getAvg($switchId, $alias, $start, $end);

        $data['alias'] = $alias;
        $data['switchId'] = $switchId;

        return $data;
    }

    public function getSwitchMonitorData(Request $request){
        $param = $request->all();
        $data = $this->getMonitorData($param['switchId'], $param['alias'], $param['time']);
        if (empty($data)) {
            return response()->json(['code'=>0, 'data' => '', 'msg' => 'no update']);
        } else {
            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        }
    }

    protected function monitorChart($switch, $alias){
        $start = strtotime(date("Y-m-d"));
        $end = time();

        $d = SwitchData::getJsonDataList($switch['id'], $alias, $start, $end);
        $xData = [];
        $yData = [];
        foreach ($d as $one) {
            $one = json_decode( json_encode( $one ),true);
            $xData[] = date("H:i", $one['created_time']);
            $yData[] = $one[$alias];
        }
        $data['switch'] = $switch;
        $data['alias'] = $alias;
        if ($d) {
            $endPoint = json_decode( json_encode( end($d) ),true);
            $data['endX'] = $endPoint['created_time'];
        } else {
            $data['endX'] = time();
        }
        $data['startValue'] = date("H:i", strtotime('-30 minute', $data['endX']));
        $data['xData'] = json_encode($xData);
        $data['yData'] = json_encode($yData);
        $sessionKey = 'switch_monitor_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $card = Card::make(view('admin.switch.monitorChart', $data));
        return $card;
    }

    public function getSwitchMonitorChart(Request $request){
        $param = $request->all();
        $time = strtotime(date("Y-m-d")." ". $param['endX']. ":00");

        $d = SwitchData::getJsonDataList($param['switchId'], $param['alias'], $param['endX']);
        if ($d) {
            $xData = [];
            $yData = [];
            foreach ($d as $one) {
                $one = json_decode( json_encode( $one ),true);
                $xData[] = date("H:i", $one['created_time']);
                $yData[] = $one[$param['alias']];
            }
            $data['xData'] = $xData;
            $data['yData'] = $yData;
            $endPoint = json_decode( json_encode( end($d) ),true);
            $data['endX'] = $endPoint['created_time'];
            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        } else {
            return response()->json(['code'=>0, 'data' => [], 'msg' => 'no update']);
        }
    }

    //*************************************************************************************************
    //*************************************************************************************************

    public function history(Content $content, $id = 0)
    {   
        Admin::css('/layui/css/layui.css');

        return $content
            ->header('历史电量')
            ->description('')
            ->body(function (Row $row) use ($id) {
                $row->column(12, function (Column $column) use ($id) {
                    $switch = SwitchModel::find($id);
                    $column->row(function(Row $row) use ($switch) {
                        $row->column(12, '<div style="text-align: center; font-size: 22px;margin: 20px">'.$switch['name'].'</div>');
                    });
                    $column->row($this->historyGrid($switch));
                });
            });
    }

    protected function historyGrid($switch){
        $m = SwitchElectric::where('switch_id', $switch['id'])->orderBy('created_time', 'desc');

        return Grid::make($m, function (Grid $grid) {
            $grid->setActionClass(Grid\Displayers\Actions::class);
            $grid->column('quantity','当日电量');
            $grid->column('created_time','日期')->display(function ($time) {
                return date("Y-m-d", $time);
            });

            $grid->disableCreateButton();
            $grid->disableActions();

            $grid->showFilter();
            $grid->showFilterButton();
            $grid->filter(function($filter){
                // 展开过滤器
                $filter->panel();
                $filter->between('created_time', '日期')->datetime()->toTimestamp();
            });
            
            $grid->header(function ($collection) use ($grid) {
                $query = SwitchElectric::query();

                // 拿到表格筛选 where 条件数组进行遍历
                $grid->model()->getQueries()->unique()->each(function ($value) use (&$query) {
                    if (in_array($value['method'], ['paginate', 'get', 'orderBy', 'orderByDesc'], true)) {
                        return;
                    }

                    $query = call_user_func_array([$query, $value['method']], $value['arguments'] ?? []);
                });

                // 查出统计数据
                $data = $query->get()->toArray();
                $total = 0.000;
                if ($data) {
                    foreach ($data as $one) {
                        $total += $one['quantity'];
                    }
                }
                return "<div style='padding: 10px;'>合计电量 ： $total</div>";
            });


        });
    }



    public function setSwitchStatus(Request $request){
        $param = $request->all();
        $switch = SwitchModel::find($param['switchId']);
        $parent = SwitchModel::find($switch['pid']);
        if ($param['status']) { //开
            $res = SwitchModel::setSwitchOn($parent['machine_code'], $param['switchId'], $switch['phase'], $switch['machine_code']);
        } else {    //关
            $res = SwitchModel::setSwitchOff($parent['machine_code'], $param['switchId'], $switch['phase'], $switch['machine_code']);
        }

        if ($res) {
            return response()->json(['code'=>1, 'msg' => 'success']);
        } else {
            return response()->json(['code'=>0, 'msg' => 'fail']);
        }
    }
}
